home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / SourceCode / AdobeExamples / NX_Scroll / DrawingView.m < prev    next >
Text File  |  1992-12-19  |  12KB  |  521 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    DrawingView.m
  35.  *
  36.  *    This view represents the page that the image is drawn onto. It is
  37.  *    a subview of the DocView. The DocView is the document view of
  38.  *    the ClipView. This view's real size grows with the scale but the
  39.  *    bounds always stays the same.
  40.  *
  41.  *
  42.  *    Version:    2.0
  43.  *    Author:    Ken Fromm
  44.  *    History:
  45.  *            03-07-91        Added this comment.
  46.  */
  47.  
  48. #import "DrawingView.h"
  49. #import "DrawingViewWraps.h"
  50. #import "DocView.h"
  51. #import "Graphic.h"
  52. #import "ScrollApp.h"
  53. #import <objc/List.h>
  54. #import <appkit/Button.h>
  55. #import <appkit/Control.h>
  56. #import <appkit/Matrix.h>
  57. #import <appkit/nextstd.h>
  58. #import <dpsclient/dpsclient.h>
  59. #import <dpsclient/wraps.h>
  60.  
  61. extern void initGparms();
  62. extern void setGparms();
  63.  
  64. @implementation DrawingView
  65.  
  66. /*
  67. *    Allocate a gstate, set the clipping to NO because it will be clipped
  68. *    by the clip view.
  69. */
  70. +newFrame:(NXRect *) frm
  71. {    
  72.     self = [super newFrame:frm]; 
  73.     
  74.     drawUpath = [NXApp  getUpathBuffer];
  75.     drawManner = UPATH;
  76.     
  77.     return self;
  78. }
  79.  
  80. - free
  81. {
  82.     [self  freeGraphics];
  83.  
  84.     return [super free];
  85. }
  86.  
  87. - setFieldsMode:(BOOL) mode
  88. {
  89.     displayFields = eraseFields = mode;
  90.  
  91.     return self;
  92. }
  93.  
  94. - setTypeOfDrawing:sender
  95. {
  96.     id        matrixId;
  97.  
  98.     drawFrame = ([sender selectedRow] == 1);
  99.  
  100.     matrixId = [NXApp  getStrokingMatrix];
  101.     [[matrixId cellAt:0 :0] setEnabled:drawFrame];
  102.     [[matrixId cellAt:1 :0] setEnabled:drawFrame];
  103.  
  104.     matrixId = [NXApp  getParameterMatrix];
  105.     [[matrixId cellAt:0 :0] setEnabled:!drawFrame];
  106.     [[matrixId cellAt:1 :0] setEnabled:!drawFrame];
  107.  
  108.     [NXApp  redrawAction:self];
  109.  
  110.     return self;
  111. }
  112.  
  113. - setSelectivity:sender
  114. {
  115.     drawEverything = ([sender selectedRow] == 1);  
  116.  
  117.     [NXApp  redrawAction:self];
  118.  
  119.     return self;
  120. }
  121.  
  122. - setDrawingManner:sender
  123. {
  124.     drawManner = [sender selectedRow];
  125.  
  126.     [NXApp  redrawAction:self];
  127.  
  128.     return self;
  129. }
  130.  
  131. - setStroking:sender
  132. {
  133.     drawCombined = ([sender selectedRow] == 1);
  134.  
  135.     [NXApp  redrawAction:self];
  136.  
  137.     return self;
  138. }
  139.  
  140. - setParameterSetting:sender
  141. {
  142.     drawEveryPath = ([sender selectedRow] == 1);
  143.  
  144.     [NXApp  redrawAction:self];
  145.  
  146.     return self;
  147. }
  148.  
  149. -setDrawOrigin:(NXPoint *)origin
  150. {
  151.     drawOrigin = *origin;
  152.     
  153.     return self;
  154. }
  155.  
  156. - freeGraphics
  157. {
  158.     if (graphicsListId)
  159.         [graphicsListId  freeObjects];
  160.         
  161.     [graphicsListId free];
  162.  
  163.     return self;
  164. }
  165.  
  166. - insertList:listId
  167. {
  168.     [self  freeGraphics];
  169.     graphicsListId = listId;
  170.  
  171.     return self;
  172. }
  173.  
  174. - eraseFields:sender
  175. {
  176.     id        matrixId;
  177.  
  178.     int        i;
  179.  
  180.     matrixId = [NXApp getTimingMatrix];
  181.     for (i= 0; i < [matrixId cellCount]; i++)
  182.         [[matrixId cellAt:i :0] setStringValue:""];
  183.  
  184.     matrixId = [NXApp getStatusMatrix];
  185.     for (i= 0; i < [matrixId cellCount]; i++)
  186.         [[matrixId cellAt:i :0] setStringValue:""];
  187.  
  188.     return self;
  189. }
  190.  
  191. - displayFields:sender
  192. {
  193.     id        matrixId;
  194.  
  195.     int        i, ucache_values[5];
  196.     
  197.      if (timing_info.num_draws)
  198.     {
  199.         matrixId = [NXApp getTimingMatrix];
  200.         [[matrixId cellAt:0 :0]
  201.             setFloatValue:timing_info.num_draws];
  202.         [[matrixId cellAt:1 :0]
  203.             setFloatValue:timing_info.drawingtime/timing_info.num_draws];
  204.         if (!drawFrame)
  205.         {
  206.             [[matrixId cellAt:2 :0]
  207.                 setFloatValue:timing_info.num_fills/timing_info.num_draws];
  208.             [[matrixId cellAt:3 :0]
  209.                 setFloatValue:timing_info.num_strokes/timing_info.num_draws];
  210.         }
  211.         else
  212.             [[matrixId cellAt:3 :0]
  213.                 setFloatValue:timing_info.num_strokes/timing_info.num_draws];
  214.         [[matrixId cellAt:4 :0]
  215.             setFloatValue:timing_info.num_subpaths/timing_info.num_draws];
  216.     }
  217.  
  218.     if (drawManner == UCACHE)
  219.     {
  220.         matrixId = [NXApp getStatusMatrix];
  221.         PSWUcachestatus(&ucache_values[0], &ucache_values[1],
  222.             &ucache_values[2], &ucache_values[3], &ucache_values[4]);
  223.         for (i= 0; i < [matrixId cellCount]; i++)
  224.             [[matrixId cellAt:i :0] setIntValue:ucache_values[i]];
  225.     }
  226.  
  227.     /* Prepare for next time around. */
  228.     timing_info.num_fills = timing_info.num_strokes = 0;
  229.     timing_info.num_subpaths = timing_info.num_draws = 0;
  230.     timing_info.drawingtime = 0.0;
  231.  
  232.     return self;
  233. }
  234.  
  235. /*
  236. *    If the docview is zooming, then scale the drawing view.
  237. */
  238. - mouseDown:(NXEvent *)event
  239. {
  240.     NXPoint        p;
  241.     
  242.      p = event->location; 
  243.     if ([superview  isZooming])
  244.     {
  245.         displayFields = eraseFields = YES;
  246.         return [nextResponder  scaleDrawView:self  toPoint:&p];
  247.     }
  248.  
  249.     return self;
  250. }
  251.  
  252. /*
  253. *    Initialize the user path structure. Always include a ucache. 
  254. *    If ucache is not used then start at the second entry in the op
  255. *    array and decrement num_ops by one.
  256. */
  257. static void initUpath(UPath *aUpath)
  258. {    
  259.     aUpath->ops[0] = dps_ucache;
  260.     aUpath->num_ops = 1;
  261.  
  262.     aUpath->pts[0] = 99999;
  263.     aUpath->pts[1] = 99999;
  264.     aUpath->pts[2] = -99999;
  265.     aUpath->pts[3] = -99999;
  266.     aUpath->num_pts = 4;
  267. }
  268.  
  269. /*
  270. *    Increment the stroke count and stroke the existing path.
  271. */
  272. static void strokeRedBook(int *strokes)
  273. {
  274.     *strokes += 1;
  275.     PSstroke();
  276. }
  277.  
  278. /*
  279. *    Call the appropriate wrap to construct the path. Not the recommended
  280. *    approach to drawing (user paths are). Made external so Graphic.m
  281. *    can make use of it.
  282. */
  283. void makeRedBook(UPath *aUpath)
  284. {
  285.     int        i_op, i_pt;
  286.     
  287.     i_pt = 4;
  288.  
  289.     /* Skip the ucache operator. */
  290.     for (i_op = 1; i_op < aUpath->num_ops; i_op++)
  291.     {
  292.         switch (aUpath->ops[i_op])
  293.         {
  294.             case dps_moveto:
  295.                 PSmoveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
  296.                 i_pt += 2;
  297.                 break;
  298.             case dps_rmoveto:
  299.                 PSrmoveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
  300.                 i_pt += 2;
  301.                 break;
  302.             case dps_lineto:
  303.                 PSlineto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
  304.                 i_pt += 2;
  305.                 break;
  306.             case dps_rlineto:
  307.                 PSrlineto(aUpath->pts[i_pt], aUpath->pts[i_pt+1]);
  308.                 i_pt += 2;
  309.                 break;
  310.             case dps_curveto:
  311.                 PScurveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1],
  312.                     aUpath->pts[i_pt+2], aUpath->pts[i_pt+3],
  313.                     aUpath->pts[i_pt+4], aUpath->pts[i_pt+5]);
  314.                 i_pt += 6;
  315.                 break;
  316.             case dps_rcurveto:
  317.                 PSrcurveto(aUpath->pts[i_pt], aUpath->pts[i_pt+1],
  318.                     aUpath->pts[i_pt+2], aUpath->pts[i_pt+3],
  319.                     aUpath->pts[i_pt+4], aUpath->pts[i_pt+5]);
  320.                 i_pt += 6;
  321.                 break;
  322.             case dps_closepath:
  323.                 PSclosepath();
  324.                 break;
  325.         }
  326.     }
  327. }
  328.  
  329. /*
  330. *    If the ucache is to be used then include the first operator
  331. *    otherwise skip it.
  332. */
  333. static void strokeUpath(UPath *aUpath, int manner, int *strokes)
  334. {
  335.     *strokes += 1;
  336.     if (manner == UCACHE)
  337.         DPSDoUserPath(&aUpath->pts[4], aUpath->num_pts - 4, dps_float,
  338.             &aUpath->ops[0], aUpath->num_ops, aUpath->pts, dps_ustroke);    
  339.     else
  340.         DPSDoUserPath(&aUpath->pts[4], aUpath->num_pts - 4, dps_float,
  341.             &aUpath->ops[1], aUpath->num_ops-1, aUpath->pts, dps_ustroke);
  342. }
  343.  
  344. /*
  345. *    Omit the bounding box numbers at the beginning of the operand
  346. *    array as well as the dps_ucache at the beginning of the operator
  347. *    array. Update the bounding box of the user path if necessary.
  348. */
  349. - getUpath:(NXRect *) r  fromGraphic:graphicId
  350. {
  351.     int        ops_before;
  352.     
  353.     UPath    *gUpath;
  354.  
  355.     [graphicId  getUpath:&gUpath forRect:r];
  356.     if (gUpath)
  357.     {
  358.         timing_info.num_subpaths++;
  359.         if (!drawCombined)
  360.         {
  361.             if (drawManner == REDBOOK)
  362.             {
  363.                 makeRedBook(gUpath);
  364.                 strokeRedBook(&timing_info.num_strokes);
  365.             }
  366.             else
  367.                 strokeUpath(gUpath, drawManner, &timing_info.num_strokes);
  368.         }
  369.         else
  370.         {
  371.             if (drawUpath->num_pts + gUpath->num_pts > PTS_UPATH_BUFFER ||
  372.                   drawUpath->num_ops + gUpath->num_ops > OPS_UPATH_BUFFER)
  373.             {
  374.                 if (drawManner == REDBOOK)
  375.                     strokeRedBook(&timing_info.num_strokes);
  376.                 else
  377.                     strokeUpath(drawUpath, drawManner, &timing_info.num_strokes);
  378.  
  379.                 initUpath(drawUpath);
  380.             }
  381.             
  382.             if (drawManner == REDBOOK)
  383.                 makeRedBook(gUpath);
  384.             else
  385.             {
  386.                 bcopy(&gUpath->pts[4], &drawUpath->pts[drawUpath->num_pts],
  387.                     (gUpath->num_pts - 4)* (sizeof(float)/sizeof(char)));
  388.                 bcopy(&gUpath->ops[1], &drawUpath->ops[drawUpath->num_ops],
  389.                     gUpath->num_ops-1);
  390.  
  391.                 drawUpath->pts[0] = MIN(gUpath->pts[0], drawUpath->pts[0]);
  392.                 drawUpath->pts[1] = MIN(gUpath->pts[1], drawUpath->pts[1]);
  393.                 drawUpath->pts[2] = MAX(gUpath->pts[2], drawUpath->pts[2]);
  394.                 drawUpath->pts[3] = MAX(gUpath->pts[3], drawUpath->pts[3]);
  395.             }
  396.  
  397.             drawUpath->num_pts += gUpath->num_pts-4;
  398.             drawUpath->num_ops += gUpath->num_ops-1;
  399.         }
  400.     }
  401.  
  402.     return self;
  403. }
  404.  
  405. /*
  406. *    Compare the bounds of the object with the rectangle to draw in order to
  407. *    eliminate unnecessary drawing. The modal session stuff is just to
  408. *    intercept the selection of the redraw button in the interface during
  409. *    a trace. (This stops the drawing. It's only check during a trace
  410. *    because the trace can be quite long.)
  411. */
  412. - drawSelf:(NXRect *)r :(int) count
  413. {
  414.     int            i, num, ElapsedTime;
  415.  
  416.     BOOL        tracing;
  417.  
  418.     GParms        parms;
  419.     GParms        *p_parms;
  420.     
  421.     NXRect        rect;
  422.     NXRect        *p_rect;
  423.  
  424.     NXModalSession    theSession;
  425.  
  426.     if (eraseFields)
  427.     {
  428.         [self  eraseFields:self];
  429.         eraseFields = NO;
  430.     }
  431.  
  432.     PSsetgray(NX_WHITE);
  433.     NXRectFill(r);
  434.  
  435.     initGparms(&parms);
  436.     if (drawFrame)
  437.     {
  438.         parms.linewidth = 0.05;
  439.         initUpath(drawUpath);
  440.     }
  441.     else
  442.     {
  443.         if (drawEveryPath)
  444.             p_parms = NULL;
  445.         else
  446.             p_parms = &parms;
  447.     }
  448.     setGparms(&parms);
  449.     NXSetColor(parms.color);
  450.     
  451.     if (drawEverything)
  452.         p_rect = NULL;
  453.     else
  454.     {
  455.         rect = *r;
  456.         rect.origin.x += drawOrigin.x;
  457.         rect.origin.y += drawOrigin.y;
  458.         p_rect = ▭
  459.     }
  460.     
  461.     tracing = [NXApp  tracing];
  462.     if (tracing)
  463.     {
  464.         [[NXApp redrawButton]  setTitle:"STOP"];
  465.  
  466.         [NXApp beginModalSession:&theSession for:[NXApp  methodsWindow]];
  467.         DPSTraceContext(DPSGetCurrentContext(), YES);
  468.     }
  469.  
  470.     PSgsave();
  471.     NXRectClip(r);
  472.     PStranslate(-drawOrigin.x, -drawOrigin.y);
  473.     PSWMarkTime ();  NXPing();
  474.         num = [graphicsListId count];
  475.         for (i = 0; i < num; i++)
  476.         {
  477.             if (tracing && (i % MODALTRACE == 0))
  478.                 if ([NXApp runDrawModalSession:&theSession] != NX_RUNCONTINUES)
  479.                     break;
  480.  
  481.             if (drawFrame)
  482.                 [self  getUpath:p_rect  fromGraphic:[graphicsListId  objectAt:i]];
  483.             else
  484.                 [[graphicsListId  objectAt:i]  drawObject:p_rect  currentParms:p_parms
  485.                     withManner:drawManner  timingInfo:&timing_info];
  486.         }
  487.  
  488.         if (drawFrame && drawCombined)
  489.         {
  490.             if (drawManner == REDBOOK)
  491.                 strokeRedBook(&timing_info.num_strokes);
  492.             else
  493.                 strokeUpath(drawUpath, drawManner, &timing_info.num_strokes);
  494.         }
  495.  
  496.     PSWReturnTime (&ElapsedTime);
  497.     PSgrestore();
  498.  
  499.     if (tracing)
  500.     {
  501.         DPSTraceContext(DPSGetCurrentContext(), NO);
  502.         [NXApp endModalSession:&theSession];
  503.  
  504.         [[NXApp redrawButton]  setTitle:"redraw"];
  505.     }
  506.  
  507.     timing_info.drawingtime += ElapsedTime;
  508.     ++timing_info.num_draws;
  509.  
  510.     if (displayFields)
  511.     {
  512.         [self  displayFields:self];
  513.         displayFields = NO;
  514.         eraseFields = YES;
  515.     }
  516.  
  517.     return self;            
  518. }
  519.  
  520. @end
  521.